package org.yn.user.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.yn.base.constants.BaseConstants;
import org.yn.base.util.SMSUtils;
import org.yn.base.util.StrUtils;
import org.yn.base.util.VerifyCodeUtils;
import org.yn.exception.AssertUtil;
import org.yn.exception.BusinessException;
import org.yn.exception.ResponseCode;
import org.yn.user.domain.User;
import org.yn.user.dto.BindSendSmsCodeDTO;
import org.yn.user.dto.RegisterSendSmsCodeDTO;
import org.yn.user.mapper.UserMapper;
import org.yn.user.service.VerifyCodeService;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    UserMapper userMapper;

    @Autowired
   private SMSUtils smsUtils;
    @Autowired
  private   RedisTemplate redisTemplate;

    @Override
    public String getImage(String imageCodeKey) throws IOException {
        // 生成6位或4位随机字符
//        String randomString = StrUtils.getRandomString(6);
        String randomString="1234";  //这里为方便开发测试 用1234
        //将随机的数 放在redis中，imageCodeKey作为key  设置过期时间   5分钟
        redisTemplate.opsForValue().set(imageCodeKey,randomString,5, TimeUnit.MINUTES);

        //生成图片
        String base64Image = VerifyCodeUtils.VerifyCode(135, 42, randomString);
        System.out.printf("生成的验证码:"+randomString);

        return base64Image;
    }

    @Override
    public void registerSendSmsCode(RegisterSendSmsCodeDTO dto) {
        // 参数校验
        // imageCodeKey不能为空   断言
        AssertUtil.isNotBlank(dto.getImageCodeKey(), ResponseCode.RESPONSE_CODE_500);

        // 校验图片验证码
        // 将图片验证码从redis取出

        String imageCodeRedis =(String)redisTemplate.opsForValue().get(dto.getImageCodeKey());

        // 如果redis中的图片验证码为空,说明过期,要让用户重新获取
        AssertUtil.isNotBlank(imageCodeRedis,ResponseCode.RESPONSE_CODE_40017);

        // 断言 前端和redis的值 是否一样
        AssertUtil.isEqIgnoreCase(imageCodeRedis,dto.getImageCode(),ResponseCode.RESPONSE_CODE_40016);

        //验证改手机号的用户是否存在 是否已经注册
        User user = userMapper.selectByPhone(dto.getPhone());

        //断言判空
        AssertUtil.isNull(user,ResponseCode.RESPONSE_CODE_40018);


        //判断redis中是否有手机验证码  没有则发送
        //redis中key 手机号码+_sms      value为手机验证码:发送时间
        String prefix = BaseConstants.REGISTER_SMS_VERIFY_CODE_KEY;


        sendSms(dto.getPhone(), prefix);

    }

    /**
     * 绑定页面发送的短信
     * @param dto
     */
    @Override
    public void bindSendSmsCode(BindSendSmsCodeDTO dto) {

        //校验  手机号
        String phone = dto.getPhone();
        AssertUtil.isNotBlank(phone, ResponseCode.RESPONSE_CODE_500);

        // 发送短信
        sendSms(phone,BaseConstants.BIND_SMS_VERIFY_CODE_KEY);


    }

    /**
     * 提取出发短信的功能
     * @param phone
     * @param prefix
     */
    private void sendSms(String phone, String prefix) {
       String key = prefix+phone;

        String smsCodeByRedis = (String)redisTemplate.opsForValue().get(key);
        //判断存在
        String smsCode = "";   //手机验证码
        if(StringUtils.isNotBlank(smsCodeByRedis)){
            // 如果已存在,判断有没有过重发时间,如果没过重发时间,就返回错误信息,
            // 过了重发时间将验证码重新放入redis并设置过期时间,将验证码重新发给用户
            smsCode = smsCodeByRedis.split(":")[0];
            String sendTime = smsCodeByRedis.split(":")[1];
            // 判断有没有过重发时间
            // 当前时间-发送时间 > 1分钟 过了重发时间   <1分钟 没过重发时间
            if(System.currentTimeMillis() - Long.parseLong(sendTime) < 60*1000){
                throw new BusinessException(ResponseCode.RESPONSE_CODE_40019);
            }
        }else{
            // 如果不存在,重新生成验证码,放入redis中,
            // 设置过期时间,将验证码发送给用户
            //生成4位数的数字随机验证码
            smsCode = StrUtils.getRandomString(4);
        }

        // 将验证码和当前时间存入redis
        String value = smsCode+":"+System.currentTimeMillis();

        redisTemplate.opsForValue().set(key,value,5,TimeUnit.MINUTES);    //设置5分钟

        // 发送验证码给用户的手机号

//        smsUtils.sendMessage(phone,smsCode);
        System.out.printf("-----短信为-----"+smsCode);

    }
}
